home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / lisp / eulisp / mpfeel.lha / MPFeel / listops.c < prev    next >
C/C++ Source or Header  |  1992-10-06  |  8KB  |  360 lines

  1. /* ******************************************************************** */
  2. /* listops.c         Copyright (C) Codemist and University of Bath 1989 */
  3. /*                                                                      */
  4. /* further list operations                                        */
  5. /* ******************************************************************** */
  6.  
  7. /*
  8.  * $Id: listops.c,v 1.5 1992/01/07 22:15:36 pab Exp $
  9.  *
  10.  * $Log: listops.c,v $
  11.  * Revision 1.5  1992/01/07  22:15:36  pab
  12.  * ncc compatable, plus backtrace
  13.  *
  14.  * Revision 1.4  1991/12/22  15:14:15  pab
  15.  * Xmas revision
  16.  *
  17.  * Revision 1.3  1991/09/22  19:14:35  pab
  18.  * Fixed obvious bugs
  19.  *
  20.  * Revision 1.2  1991/09/11  12:07:20  pab
  21.  * 11/9/91 First Alpha release of modified system
  22.  *
  23.  * Revision 1.1  1991/08/12  16:49:43  pab
  24.  * Initial revision
  25.  *
  26.  * Revision 1.4  1991/02/13  18:22:07  kjp
  27.  * Pass.
  28.  *
  29.  */
  30.  
  31. /*
  32.  * Change Log:
  33.  *   Version 1, March 1990 (Compiler rationalisation)
  34.  */
  35.  
  36. #include "defs.h"
  37. #include "structs.h"
  38. #include "funcalls.h"
  39.  
  40. #include "error.h"
  41. #include "global.h"
  42. #include "modboot.h"
  43. #include "symboot.h"
  44. #include "calls.h"
  45. #include "modules.h"
  46. #include "ngenerics.h"
  47.  
  48. LispObject flat_list_copy(LispObject *);
  49.  
  50. EUFUN_1( Fn_null, form)
  51. {
  52.   return (form==nil?lisptrue:nil);
  53. }
  54. EUFUN_CLOSE
  55.  
  56.                 /* Destructive append */
  57. EUFUN_2( Fn_nconc,  form1, form2)
  58. {
  59.   LispObject p = form1;
  60.   if (!is_cons(form1)) return(form2);
  61.   while (CDR(p)!=nil) p = CDR(p);
  62.   CDR(p) = form2;
  63.   return form1;
  64. }
  65. EUFUN_CLOSE
  66.  
  67. EUFUN_2( Fn_append,  l1, l2)
  68. {
  69.   LispObject endptr,walker,val;
  70.  
  71.   if (!is_cons(l1)) return(l2);
  72.  
  73.   /* reasonable append */
  74.   
  75.   val = EUCALL_2(Fn_cons,CAR(l1),nil);
  76.   STACK_TMP(val);
  77.   endptr = val;
  78.   walker = CDR(ARG_0(stackbase)/*l1*/);
  79.   while (is_cons(walker))
  80.     {
  81.       LispObject xx;
  82.       STACK_TMP(endptr);
  83.       STACK_TMP(CDR(walker));
  84.       xx = EUCALL_2(Fn_cons, CAR(walker), nil);
  85.       UNSTACK_TMP(walker);
  86.       UNSTACK_TMP(endptr);
  87.       CDR(endptr)=xx;
  88.       endptr=CDR(endptr);
  89.     }
  90.   CDR(endptr) = ARG_1(stackbase)/*l2*/;
  91.   UNSTACK_TMP(val);
  92.   return(val);
  93. }
  94. EUFUN_CLOSE
  95.  
  96.                 /* Simple predicate for NULL */
  97. EUFUN_1( Fn_lastpair, form)
  98. {
  99.   while (!is_cons(form))
  100.     form = CallError(stacktop,"Not a list in last-pair",form,CONTINUABLE);
  101.   while (CDR(form)!=nil) form = CDR(form);
  102.   return form;
  103. }
  104. EUFUN_CLOSE
  105.  
  106. EUFUN_1( Fn_nreverse, form)
  107. {
  108.   LispObject x=nil;
  109.   while (form!=nil) {
  110.     LispObject y = CDR(form);
  111.     CDR(form) = x;
  112.     x = form;
  113.     form = y;
  114.   }
  115.   return x;
  116. }
  117. EUFUN_CLOSE
  118.  
  119. EUFUN_3( Fn_assoc, obj, list, fn)
  120. {
  121.   while (list!=nil) {
  122.     LispObject xx;
  123.     EUCALLSET_3(xx,apply2,ARG_2(stackbase),ARG_0(stackbase),CAR(CAR(list)));
  124.     if (xx != nil)  {
  125.       list=ARG_1(stackbase);
  126.       return CAR(list);
  127.     }
  128.     list = ARG_1(stackbase);
  129.     list = CDR(list);
  130.     ARG_1(stackbase) = list;
  131.   }
  132.   return nil;
  133. }
  134. EUFUN_CLOSE
  135.  
  136. EUFUN_3( Fn_member, obj, list, fn)
  137. {
  138.   while (list!=nil) {
  139.     if (EUCALL_3(apply2,ARG_2(stackbase),ARG_0(stackbase),CAR(list)) != nil) {
  140.       return ARG_1(stackbase);
  141.     }
  142.     list = ARG_1(stackbase);
  143.     list = CDR(list);
  144.     ARG_1(stackbase) = list;
  145.   }
  146.   return nil;
  147. }
  148. EUFUN_CLOSE
  149.  
  150. EUFUN_2( Fn_memq,  obj, list)
  151. {
  152.   if (!is_cons(list) && list != nil)
  153.     CallError(stacktop,"memq: non-lists passed",list,NONCONTINUABLE);
  154.  
  155.   while (is_cons(list)) {
  156.     if (obj == CAR(list))
  157.       return(lisptrue);
  158.     else
  159.       list = CDR(list);
  160.   }
  161.   
  162.   return(nil);
  163. }
  164. EUFUN_CLOSE
  165.  
  166. /* ******************************************************************** */
  167. /*                            Lisp Mappers                              */
  168. /* ******************************************************************** */
  169.  
  170. static LispObject mapcar_apply_args(LispObject *stackbase, LispObject set)
  171. {
  172.   LispObject walker,res,ptr;
  173.   LispObject *stacktop=stackbase+1;
  174.  
  175.   ARG_0(stackbase)=nil;
  176.   res = nil; ptr = nil;
  177.  
  178.   walker = set;
  179.   while (is_cons(walker)) 
  180.     {
  181.       if (!is_cons(CAR(walker))) 
  182.     return(nil);
  183.  
  184.       STACK_TMP(CDR(walker));
  185.       if (ptr == nil)
  186.     {
  187.       EUCALLSET_2(res, Fn_cons,CAR(CAR(walker)),nil);
  188.       ARG_0(stackbase)=res;
  189.       ptr = res;
  190.     }
  191.       else
  192.     {
  193.       LispObject xx;
  194.       STACK_TMP(ptr);
  195.       EUCALLSET_2(xx, Fn_cons, CAR(CAR(walker)),nil);
  196.       UNSTACK_TMP(ptr);
  197.       CDR(ptr) = xx;
  198.       ptr = CDR(ptr);
  199.     }
  200.       UNSTACK_TMP(walker);
  201.     }
  202.   res=ARG_0(stackbase);
  203.   return(res);
  204. }
  205.  
  206. static LispObject mapcar_advance_lists(LispObject set)
  207.   LispObject walker = set;
  208.  
  209.   while (is_cons(walker)) {
  210.     CAR(walker) = CDR(CAR(walker));
  211.     walker = CDR(walker);
  212.   }
  213.   
  214.   return(set);
  215. }
  216.  
  217. EUFUN_3( Fn_mapcar, fn, l1, lists)
  218. {
  219.   LispObject flat_list_copy(LispObject *);
  220.   
  221.   if (!is_cons(l1) && l1 != nil)
  222.     CallError(stacktop,"mapcar: not a list",l1,NONCONTINUABLE);
  223.  
  224.   ARG_3(stackbase)=nil;
  225.   stacktop++;
  226.  
  227.   {
  228.     LispObject set,args;
  229.     LispObject res,ptr,val;
  230.     
  231.     /* More general... */
  232.  
  233.     EUCALLSET_1(set, flat_list_copy, lists);
  234.     EUCALLSET_2(set, Fn_cons,ARG_1(stackbase),set);
  235.  
  236.     res = nil; ptr = nil;
  237.       
  238.     while (TRUE) 
  239.       {
  240.  
  241.     /* Construct args to apply... */
  242.       
  243.     STACK_TMP(set);    
  244.     STACK_TMP(ptr);
  245.     if ((args = mapcar_apply_args(stacktop,set)) == nil) 
  246.       {    
  247.         res=ARG_3(stackbase);
  248.         return(res);
  249.       }
  250.     UNSTACK_TMP(ptr);
  251.     STACK_TMP(ptr);
  252.     EUCALLSET_2(val,module_mv_apply_1,ARG_0(stackbase),args);
  253.     UNSTACK_TMP(ptr);
  254.       
  255.     if (ptr == nil)
  256.       {
  257.         EUCALLSET_2(res, Fn_cons,val,nil);
  258.         ARG_3(stackbase)=res;
  259.         ptr = res;
  260.       }
  261.     else 
  262.       {
  263.         LispObject xx;
  264.         STACK_TMP(ptr);
  265.         EUCALLSET_2(xx, Fn_cons, val,nil);
  266.         UNSTACK_TMP(ptr);
  267.         CDR(ptr) = xx;
  268.         ptr = CDR(ptr);
  269.       }
  270.     UNSTACK_TMP(set);
  271.     mapcar_advance_lists(set);
  272.       }
  273.   }
  274.  
  275.   return(nil);
  276. }
  277. EUFUN_CLOSE
  278.  
  279. EUFUN_3( Fn_mapc, fn, l1, lists)
  280. {
  281.  
  282.   if (!is_cons(l1) && l1 != nil)
  283.     CallError(stacktop,"mapc: not a list",l1,NONCONTINUABLE);
  284.  
  285.   if (FALSE) {
  286.     ;
  287.   }
  288.   else {
  289.     LispObject set,args;
  290.     
  291.     /* More general... */
  292.  
  293.     EUCALLSET_1(set,flat_list_copy,lists);
  294.     EUCALLSET_2(set, Fn_cons,ARG_1(stackbase),set);
  295.  
  296.     while (TRUE) {
  297.       LispObject dummy;
  298.  
  299.       /* Construct args to apply... */
  300.  
  301.       STACK_TMP(set);
  302.       if ((args = mapcar_apply_args(stacktop,set)) == nil) {
  303.     return(nil);
  304.       }
  305.       UNSTACK_TMP(set);
  306.  
  307.       STACK_TMP(set);
  308.       EUCALL_2(module_mv_apply_1,ARG_0(stackbase),args);
  309.       UNSTACK_TMP(set);
  310.       mapcar_advance_lists(set);
  311.     }
  312.   }
  313.  
  314.   return(nil);
  315. }
  316. EUFUN_CLOSE
  317.  
  318. EUFUN_1( flat_list_copy, list)
  319. {
  320.   LispObject xx;
  321.   if (!is_cons(list)) return(nil);
  322.   EUCALLSET_1(xx, flat_list_copy, CDR(list));
  323.   return(EUCALL_2(Fn_cons, CAR(ARG_0(stackbase)),xx));
  324. }
  325. EUFUN_CLOSE
  326.   
  327. /*
  328.  
  329.  * Initialise the module...
  330.  
  331.  */
  332.  
  333. #define LISTOPS_ENTRIES 11
  334. MODULE Module_listops;
  335. LispObject Module_listops_values[LISTOPS_ENTRIES];
  336.  
  337. void initialise_listops(LispObject *stacktop)
  338. {
  339.   open_module(stacktop,
  340.           &Module_listops,
  341.           Module_listops_values,
  342.           "list-operators",
  343.           LISTOPS_ENTRIES);
  344.  
  345.   (void) make_module_function(stacktop,"memq",Fn_memq,2);
  346.   (void) make_module_function(stacktop,"append",Fn_append,2);
  347.   (void) make_module_function(stacktop,"copy-list",flat_list_copy,1);
  348.   (void) make_module_function(stacktop,"null",Fn_null,1);
  349.   (void) make_module_function(stacktop,"nconc",Fn_nconc,2);
  350.   (void) make_module_function(stacktop,"last-pair",Fn_lastpair,1);
  351.   (void) make_module_function(stacktop,"nreverse",Fn_nreverse,1);
  352.   (void) make_module_function(stacktop,"assoc",Fn_assoc,3);
  353.   (void) make_module_function(stacktop,"member",Fn_member,3);
  354.   (void) make_module_function(stacktop,"mapcar",Fn_mapcar,-3);
  355.   (void) make_module_function(stacktop,"mapc",Fn_mapc,-3);
  356.  
  357.   close_module();
  358. }
  359.